package org.dromara.common.web.utils;

import cn.hutool.captcha.generator.CodeGenerator;
import cn.hutool.core.math.Calculator;
import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.RandomUtil;
import org.dromara.common.core.utils.StringUtils;

import java.io.Serial;


/**
 * @Author 刘武贵
 * @Date 2024/8/15 22:00
 * @Description 功能描述：无符号计算生成器
 */
/**
 * 无符号数学运算生成器类，继承自CodeGenerator接口
 * 该类负责生成用于处理无符号整数运算的代码
 */
public class UnsignedMathGenerator implements CodeGenerator {

    @Serial
    private static final long serialVersionUID = -5514819971774091076L;

    /**
     * 定义运算符字符串常量，用于后续的操作判断
     * 选择"+-*"作为运算符，涵盖了基本的算术操作
     * 使用常量形式定义，以方便在代码多处引用且确保值不会被意外修改
     */
    private static final String OPERATORS = "+-*";

    /**
     * 参与计算数字最大长度
     */
    private final int numberLength;

    /**
     * 构造
     */
    public UnsignedMathGenerator() {
        this(2);
    }

    /**
     * 构造
     *
     * @param numberLength 参与计算最大数字位数
     */
    public UnsignedMathGenerator(int numberLength) {
        this.numberLength = numberLength;
    }

    /**
     * 生成
     */
    @Override
    public String generate() {
        // 获取计算题结果的最大限制
        final int limit = getLimit();
        // 生成两个随机数，用于计算题的生成
        int a = RandomUtil.randomInt(limit);
        int b = RandomUtil.randomInt(limit);
        // 将两个随机数中较大的转换为字符串格式
        String max = Integer.toString(Math.max(a,b));
        // 将两个随机数中较小的转换为字符串格式
        String min = Integer.toString(Math.min(a,b));
        // 将较大数和较小数的字符串格式分别用空格右对齐到numberLength的长度，以美化输出格式
        max = StringUtils.rightPad(max, this.numberLength, CharUtil.SPACE);
        min = StringUtils.rightPad(min, this.numberLength, CharUtil.SPACE);

        // 随机选择一个运算符，拼接成一道计算题字符串并返回
        return max + RandomUtil.randomChar(OPERATORS) + min + '=';
    }

    /**
     * 验证用户输入的验证码是否正确
     *
     * @param code        图片中显示的验证码文本
     * @param userInputCode 用户输入的验证码文本
     * @return 如果用户输入的验证码与图片中的验证码一致，则返回true；否则返回false
     */
    @Override
    public boolean verify(String code, String userInputCode) {
        // 尝试将用户输入的验证码转换为整数
        int result;
        try {
            result = Integer.parseInt(userInputCode);
        } catch (NumberFormatException e) {
            // 用户输入非数字 用户输入非数字，直接返回false
            return false;
        }

        // 计算图片中验证码的整数结果
        final int calculateResult = (int) Calculator.conversion(code);
        // 比较用户输入的验证码与计算出的验证码结果是否一致
        return result == calculateResult;
    }

    /**
     * 获取验证码长度
     *
     * @return 验证码长度
     */
    public int getLength() {
        return this.numberLength * 2 + 2;
    }

    /**
     * 根据长度获取参与计算数字最大值
     *
     * @return 最大值
     */
    private int getLimit() {
        return Integer.parseInt("1" + StringUtils.repeat('0', this.numberLength));
    }
}
